package metrics

import (
	"fmt"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	log "github.com/sirupsen/logrus"
)

// Collector Prometheus 指标收集器
type Collector struct {
	// Domain 指标
	domainsTotal            *prometheus.GaugeVec
	domainStateTotal        *prometheus.GaugeVec
	domainOperationsTotal   *prometheus.CounterVec
	domainOperationErrors   *prometheus.CounterVec
	domainOperationDuration *prometheus.HistogramVec

	// Storage 指标
	storagePoolsTotal    *prometheus.GaugeVec
	storageVolumesTotal  *prometheus.GaugeVec
	storageCapacityBytes *prometheus.GaugeVec

	// Network 指标
	networksTotal *prometheus.GaugeVec

	// Task 指标
	tasksTotal   *prometheus.GaugeVec
	taskDuration *prometheus.HistogramVec
	taskRetries  *prometheus.CounterVec

	// HTTP 指标
	httpRequestsTotal   *prometheus.CounterVec
	httpRequestDuration *prometheus.HistogramVec

	// Connection 指标
	connectionStatus     prometheus.Gauge
	connectionReconnects prometheus.Counter
}

// NewCollector 创建指标收集器
func NewCollector() *Collector {
	return &Collector{
		// Domain 指标
		domainsTotal: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_domains_total",
				Help: "Total number of domains",
			},
			[]string{"persistent"},
		),
		domainStateTotal: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_domain_state_total",
				Help: "Number of domains by state",
			},
			[]string{"state"},
		),
		domainOperationsTotal: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Name: "lvm_domain_operations_total",
				Help: "Total number of domain operations",
			},
			[]string{"operation", "result"},
		),
		domainOperationErrors: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Name: "lvm_domain_operation_errors_total",
				Help: "Total number of domain operation errors",
			},
			[]string{"operation", "error_type"},
		),
		domainOperationDuration: promauto.NewHistogramVec(
			prometheus.HistogramOpts{
				Name:    "lvm_domain_operation_duration_seconds",
				Help:    "Duration of domain operations",
				Buckets: []float64{0.1, 0.5, 1, 2, 5, 10, 30},
			},
			[]string{"operation"},
		),

		// Storage 指标
		storagePoolsTotal: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_storage_pools_total",
				Help: "Total number of storage pools",
			},
			[]string{"state"},
		),
		storageVolumesTotal: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_storage_volumes_total",
				Help: "Total number of storage volumes",
			},
			[]string{"pool"},
		),
		storageCapacityBytes: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_storage_capacity_bytes",
				Help: "Storage capacity in bytes",
			},
			[]string{"pool", "type"}, // type: capacity, allocation, available
		),

		// Network 指标
		networksTotal: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_networks_total",
				Help: "Total number of networks",
			},
			[]string{"active"},
		),

		// Task 指标
		tasksTotal: promauto.NewGaugeVec(
			prometheus.GaugeOpts{
				Name: "lvm_tasks_total",
				Help: "Total number of tasks",
			},
			[]string{"status", "type"},
		),
		taskDuration: promauto.NewHistogramVec(
			prometheus.HistogramOpts{
				Name:    "lvm_task_duration_seconds",
				Help:    "Duration of task execution",
				Buckets: []float64{1, 5, 10, 30, 60, 120, 300},
			},
			[]string{"type"},
		),
		taskRetries: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Name: "lvm_task_retries_total",
				Help: "Total number of task retries",
			},
			[]string{"type"},
		),

		// HTTP 指标
		httpRequestsTotal: promauto.NewCounterVec(
			prometheus.CounterOpts{
				Name: "lvm_http_requests_total",
				Help: "Total number of HTTP requests",
			},
			[]string{"path", "status_code"},
		),
		httpRequestDuration: promauto.NewHistogramVec(
			prometheus.HistogramOpts{
				Name:    "lvm_http_request_duration_seconds",
				Help:    "Duration of HTTP requests",
				Buckets: []float64{0.001, 0.01, 0.1, 0.5, 1, 2, 5, 10},
			},
			[]string{"path"},
		),

		// Connection 指标
		connectionStatus: promauto.NewGauge(
			prometheus.GaugeOpts{
				Name: "lvm_connection_status",
				Help: "Connection status (1=connected, 0=disconnected)",
			},
		),
		connectionReconnects: promauto.NewCounter(
			prometheus.CounterOpts{
				Name: "lvm_connection_reconnects_total",
				Help: "Total number of connection reconnects",
			},
		),
	}
}

// RecordDomainOperation 记录 Domain 操作
func (c *Collector) RecordDomainOperation(operation string, duration time.Duration, err error) {
	result := "success"
	if err != nil {
		result = "error"
		c.domainOperationErrors.WithLabelValues(operation, classifyError(err)).Inc()
	}

	c.domainOperationsTotal.WithLabelValues(operation, result).Inc()
	c.domainOperationDuration.WithLabelValues(operation).Observe(duration.Seconds())
}

// UpdateDomainMetrics 更新 Domain 总体指标
func (c *Collector) UpdateDomainMetrics(persistent, transient int, stateCount map[string]int) {
	c.domainsTotal.WithLabelValues("true").Set(float64(persistent))
	c.domainsTotal.WithLabelValues("false").Set(float64(transient))

	for state, count := range stateCount {
		c.domainStateTotal.WithLabelValues(state).Set(float64(count))
	}
}

// UpdateStoragePoolMetrics 更新存储池指标
func (c *Collector) UpdateStoragePoolMetrics(active, inactive int) {
	c.storagePoolsTotal.WithLabelValues("active").Set(float64(active))
	c.storagePoolsTotal.WithLabelValues("inactive").Set(float64(inactive))
}

// UpdateStoragePoolCapacity 更新存储池容量
func (c *Collector) UpdateStoragePoolCapacity(pool string, capacity, allocation, available uint64) {
	c.storageCapacityBytes.WithLabelValues(pool, "capacity").Set(float64(capacity))
	c.storageCapacityBytes.WithLabelValues(pool, "allocation").Set(float64(allocation))
	c.storageCapacityBytes.WithLabelValues(pool, "available").Set(float64(available))
}

// UpdateStorageVolumeMetrics 更新存储卷指标
func (c *Collector) UpdateStorageVolumeMetrics(pool string, count int) {
	c.storageVolumesTotal.WithLabelValues(pool).Set(float64(count))
}

// UpdateNetworkMetrics 更新网络指标
func (c *Collector) UpdateNetworkMetrics(active, inactive int) {
	c.networksTotal.WithLabelValues("true").Set(float64(active))
	c.networksTotal.WithLabelValues("false").Set(float64(inactive))
}

// RecordTaskExecution 记录任务执行
func (c *Collector) RecordTaskExecution(taskType string, duration time.Duration, retries int) {
	c.taskDuration.WithLabelValues(taskType).Observe(duration.Seconds())
	if retries > 0 {
		c.taskRetries.WithLabelValues(taskType).Add(float64(retries))
	}
}

// UpdateTaskMetrics 更新任务总体指标
func (c *Collector) UpdateTaskMetrics(statusCount map[string]map[string]int) {
	// statusCount: map[status]map[type]count
	for status, typeCounts := range statusCount {
		for taskType, count := range typeCounts {
			c.tasksTotal.WithLabelValues(status, taskType).Set(float64(count))
		}
	}
}

// RecordHTTPRequest 记录HTTP请求
func (c *Collector) RecordHTTPRequest(path string, duration time.Duration, statusCode int) {
	c.httpRequestsTotal.WithLabelValues(path, fmt.Sprintf("%d", statusCode)).Inc()
	c.httpRequestDuration.WithLabelValues(path).Observe(duration.Seconds())
}

// SetConnectionStatus 设置连接状态
func (c *Collector) SetConnectionStatus(connected bool) {
	if connected {
		c.connectionStatus.Set(1)
	} else {
		c.connectionStatus.Set(0)
	}
}

// IncrementReconnects 增加重连次数
func (c *Collector) IncrementReconnects() {
	c.connectionReconnects.Inc()
}

// classifyError 分类错误类型
func classifyError(err error) string {
	if err == nil {
		return "none"
	}

	errMsg := err.Error()
	switch {
	case contains(errMsg, "not found"):
		return "not_found"
	case contains(errMsg, "already"):
		return "already_exists"
	case contains(errMsg, "invalid state"):
		return "invalid_state"
	case contains(errMsg, "permission"):
		return "permission_denied"
	case contains(errMsg, "connection"):
		return "connection_error"
	case contains(errMsg, "timeout"):
		return "timeout"
	default:
		return "unknown"
	}
}

func contains(s, substr string) bool {
	return len(s) > 0 && len(substr) > 0 &&
		(s == substr || len(s) > len(substr))
}

// MetricsUpdater 定期更新指标的协调器
type MetricsUpdater struct {
	collector   *Collector
	interval    time.Duration
	stopChan    chan struct{}
	updateFuncs []func()
}

// NewMetricsUpdater 创建指标更新器
func NewMetricsUpdater(collector *Collector, interval time.Duration) *MetricsUpdater {
	return &MetricsUpdater{
		collector:   collector,
		interval:    interval,
		stopChan:    make(chan struct{}),
		updateFuncs: make([]func(), 0),
	}
}

// RegisterUpdateFunc 注册更新函数
func (u *MetricsUpdater) RegisterUpdateFunc(fn func()) {
	u.updateFuncs = append(u.updateFuncs, fn)
}

// Start 开始定期更新
func (u *MetricsUpdater) Start() {
	go u.updateLoop()
	log.Info("Metrics updater started")
}

// Stop 停止更新
func (u *MetricsUpdater) Stop() {
	close(u.stopChan)
	log.Info("Metrics updater stopped")
}

// updateLoop 更新循环
func (u *MetricsUpdater) updateLoop() {
	ticker := time.NewTicker(u.interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			u.runUpdates()
		case <-u.stopChan:
			return
		}
	}
}

// runUpdates 运行所有更新函数
func (u *MetricsUpdater) runUpdates() {
	for _, fn := range u.updateFuncs {
		func() {
			defer func() {
				if r := recover(); r != nil {
					log.Errorf("Metrics update function panic: %v", r)
				}
			}()
			fn()
		}()
	}
}
